package webjoch.process.strategies.puzzles;

import java.awt.Graphics2D;
import java.util.ArrayList;

import com.rsbuddy.event.events.MessageEvent;
import com.rsbuddy.script.methods.Calculations;
import com.rsbuddy.script.methods.Npcs;
import com.rsbuddy.script.methods.Players;
import com.rsbuddy.script.task.Task;
import com.rsbuddy.script.util.Filter;
import com.rsbuddy.script.util.Random;
import com.rsbuddy.script.wrappers.Npc;
import com.rsbuddy.script.wrappers.Tile;

import webjoch.process.strategies.Puzzle;
import webjoch.wrappers.Room;

/**
 * 
 * @author Webjoch
 *
 */

public class SlidingStatues extends Puzzle{
	Room room;
	ArrayList<Npc> queue = new ArrayList<Npc>();
	boolean solved = false;
	
	@Override
	public void setRoom(Room room) {
		this.room = room;
	}
	@Override
	public boolean isValid() {
		return getStatues().length > 0;
	}

	@Override
	public Type getType() {
		return Type.SLIDING_STATUES;
	}

	@Override
	public int loop() {
		for (Npc statue : getStatues()){
			if (queue.contains(statue)) continue;
			Tile startLocation = statue.getLocation();
			Npc statueStatic = getStatic(statue.getId() - 12);
			
			if (statue.getLocation().getX() > statueStatic.getLocation().getX()){
				if (!walkTile(getTileBeside(statue))) return 0;
				statue.interact("Pull");
				waitForSlide(statue, startLocation); 
				return 0;
			}
			if (statue.getLocation().getX() < statueStatic.getLocation().getX()){
				if (!walkTile(getTileBeside(statue))) return 0;
				statue.interact("Push");
				waitForSlide(statue, startLocation); 
				return 0;
			}
			if (statue.getLocation().getY() > statueStatic.getLocation().getY() - 7){
				if (!walkTile(getTileBehind(statue))) return 0;
				statue.interact("Push");
				waitForSlide(statue, startLocation); 
				return 0;
			}
			if (statue.getLocation().getY() < statueStatic.getLocation().getY() - 7){
				if (!walkTile(getTileBehind(statue))) return 0;
				statue.interact("Pull");
				waitForSlide(statue, startLocation); 
				return 0;
			}
		}
		queue.clear();
		return 0;
	}
	
	/**
	 * Sleeps when the given statue slide
	 * @param statue the statue to wait for the slide
	 * @param start the start location of the statue
	 */
	public void waitForSlide(Npc statue, Tile start){
		for (int i = 0; i < 100; i++){
			if (!statue.getLocation().equals(start)) break;
			Task.sleep(40);
		}
		if (statue.getLocation().equals(start)) queue.add(statue);
	}
	
	@Override
	public int[] itemNeed() {
		return new int[0];
	}

	@Override
	public boolean isFinished() {
		for (Room solvedRoom : solvedRooms){
			if (solvedRoom.getLocation().equals(room.getLocation())) return true; 
		}
		if (solved) solvedRooms.add(room);
		return solved;
	}

	@Override
	public void messageReceived(MessageEvent e) {
		if (e.isAutomated()){
			if (e.getMessage().contains("hear a click")) solved = true;
		}
	}
	
	public boolean walkTile(Tile tile){
		if (Players.getLocal().getLocation().equals(tile)) return true;
		if (Calculations.distanceTo(tile) > 4){
			tile.clickOnMap(); Task.sleep(800, 1000);
			return false;
		}else{
			tile.interact("Walk here");
			for (int i = 0; i < 100; i++){
				if (Players.getLocal().getLocation().equals(tile)) return true;
				Task.sleep(50);
			}
		}
		return false;
	}
	
	public Npc[] getStatues(){
		return Npcs.getLoaded(new Filter<Npc>(){
			public boolean accept(Npc n) {
				return n.getId() >= 10954 && n.getId() <= 10957 && room.getArea().contains(n.getLocation());
			}
		});
	}
	
	public Npc getStatic(final int id){
		return Npcs.getNearest(new Filter<Npc>(){
			public boolean accept(Npc n) {
				return n.getId() == id && room.getArea().contains(n.getLocation());
			}
		});
	}
	
	public Tile getTileBehind(Npc npc){
		Tile tile = new Tile(npc.getLocation().getX(), npc.getLocation().getY() + 1);
		for (Npc statue : getStatues()){
			if (tile.equals(statue.getLocation())) randomSlide(statue, false);
		}
		return tile;
	}
	
	public Tile getTileBeside(Npc npc){
		Tile tile = new Tile(npc.getLocation().getX() - 1, npc.getLocation().getY());
		for (Npc statue : getStatues()){
			if (tile.equals(statue.getLocation())) randomSlide(statue, true);
		}
		return tile;
	}
	
	public void randomSlide(Npc statue, boolean vertical){
		Tile start = statue.getLocation();
		String action = "Push";
		while (statue.getLocation().equals(start)){
			if (walkTile(vertical ? getTileBehind(statue) : getTileBeside(statue))) statue.interact(action);
			Task.sleep(3000, 4000);
			action = Random.nextInt(0, 2) == 0 ? "Push" : "Pull";
		}
	}
	@Override
	public void onRepaint(Graphics2D g) {
		// TODO Auto-generated method stub
		
	}
}
